home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / gdb-line.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  6.9 KB  |  224 lines

  1. #include "as.h"
  2. #include "frags.h"
  3. #include "obstack.h"
  4.  
  5. /* This is a souce file that we're storing .gdbline information about */
  6. /* .gdbline refers to files by numbers.  We keep a linked list of them
  7.    We store a list of vectors for each file.  Each element of the vector
  8.    contains a line-number, a frag, and an offset within the frag. */
  9. struct g_line_file {
  10.     int    gdb_line_file_file_number;        /* fnum */
  11.     int    gdb_line_file_number_of_vectors;    /* nv */
  12.     long    gdb_line_table_offset;            /* taboff */
  13.     struct g_line_vector *gdb_line_file_vectors;    /* vec */
  14.     struct g_line_file *gdb_line_file_next_file;    /* nfile */
  15. };
  16.  
  17. /* In order to save on space (We expect there to be LOTS of lines), we
  18.    store line-number/address pairs in bunches of MAX_LINES_PER_VECTOR
  19.    (originally fifty).  Each vector descriptor contains
  20.  
  21.    gdb_line_number_of_lines    the number of line-number/address pairs
  22.                    actually in this vector.
  23.    gdb_line_lines        The actual vector.
  24.  
  25.    gdb_line_next_vector        The next vector descriptor in the linked list.
  26.  */
  27. struct g_line_vector {
  28.     int    gdb_line_number_of_lines;        /* nlines */
  29.     struct g_line *gdb_line_lines;            /* lines */
  30.     struct g_line_vector *gdb_line_next_vector;    /* nvec */
  31. };
  32.  
  33.  
  34. /* A .gdbline wants to store a line-number/address pair.  Unfortunatly, we
  35.    don't know addresses yet, so we store frag/offset which we can use to
  36.    generate the address at write-out time. */
  37. struct g_line {
  38.     int    gdb_line_line_number;            /* lno */
  39.     fragS    *gdb_line_frag;                /* lfrag */
  40.     int    gdb_line_offset;            /* loff */
  41. };
  42.  
  43.  
  44. /* The following is stolen from (gdb's? (or is it gcc's?) symseg.h file.
  45.    These structures describe the format for the line# symbolic info in
  46.    the gdb symbolic info file.  This info is not particularly useful,
  47.    except to show what we're writing into. . . */
  48.  
  49. /* Source-file information.
  50.    This describes the relation between source files and line numbers
  51.    and addresses in the program text.  */
  52.  
  53. struct sourcevector
  54. {
  55.   int length;            /* Number of source files described */
  56.   struct source *source[1];    /* Descriptions of the files */
  57. };
  58.  
  59. /* Line number and address of one line.  */
  60.  
  61. struct line
  62. {
  63.   int linenum;
  64.   int address;
  65. };
  66.  
  67. /* All the information on one source file.  */
  68.  
  69. struct source
  70. {
  71.   char *name;            /* Name of file */
  72.   int nlines;            /* Number of lines that follow */
  73.   struct line lines[1];    /* Information on each line */
  74. };
  75.  
  76. /* End of text from symseg.h */
  77.  
  78. struct g_line_file *first_file;
  79.  
  80. struct g_line_file *add_file();
  81. struct g_line_vector *add_vector();
  82.  
  83. #define MAX_LINES_PER_VECTOR 50        /* lpv */
  84.  
  85. /* We've been told that the current address corresponds to line LINENO in
  86.    file FILE_NUMBER */
  87. void
  88. gdb_line(file_number,lineno)
  89. {
  90.     struct g_line_file *f;
  91.     struct g_line_vector *v;
  92.     struct g_line *line;
  93.  
  94.     for(f=first_file;f;f=f->gdb_line_file_next_file)
  95.         if(f->gdb_line_file_file_number==file_number)
  96.             break;
  97.     if(!f) f=add_file(file_number);
  98.     v=f->gdb_line_file_vectors;
  99.     if(!v || v->gdb_line_number_of_lines==MAX_LINES_PER_VECTOR)
  100.         v=add_vector(f);
  101.     line= &(v->gdb_line_lines)[v->gdb_line_number_of_lines];
  102.     v->gdb_line_number_of_lines++;
  103.     line->gdb_line_line_number=lineno;
  104.     line->gdb_line_frag= frag_now;
  105.     line->gdb_line_offset=obstack_next_free(&frags)-frag_now->fr_literal;
  106. }
  107.  
  108. /* We've been told where to store the .line table for file FILE_NUMBER */
  109. void
  110. gdb_line_tab(file_number,offset)
  111. {
  112.     struct g_line_file *f;
  113.  
  114.     for(f=first_file;f;f=f->gdb_line_file_next_file)
  115.         if(f->gdb_line_file_file_number==file_number)
  116.             break;
  117.     if(!f) f=add_file(file_number);
  118.     if(f->gdb_line_table_offset)
  119.         as_warn("Ignoring duplicate .linetab for file %d",file_number);
  120.     else
  121.         f->gdb_line_table_offset=offset;
  122. }
  123.  
  124. /* We've got a file (FILE_NUMBER) that we haven't heard about before.  Create
  125.    an entry for it, etc. . . */
  126. struct g_line_file *
  127. add_file(file_number)
  128. {
  129.     struct g_line_file *f;
  130.  
  131.     f=(struct g_line_file *)xmalloc(sizeof(struct g_line_file));
  132.     f->gdb_line_file_file_number=file_number;
  133.     f->gdb_line_table_offset = 0;
  134.     f->gdb_line_file_number_of_vectors=0;
  135.     f->gdb_line_file_vectors=(struct g_line_vector *)0;
  136.     f->gdb_line_file_next_file=first_file;
  137.     first_file=f;
  138.     return f;
  139. }
  140.  
  141. /* The last vector for file F is full.  Allocate a new one. */
  142. struct g_line_vector *
  143. add_vector(f)
  144. struct g_line_file *f;
  145. {
  146.     struct g_line_vector *tmp_vec;
  147.  
  148.     f->gdb_line_file_number_of_vectors++;
  149.     tmp_vec=(struct g_line_vector *)xmalloc(sizeof(struct g_line_vector));
  150.     tmp_vec->gdb_line_number_of_lines=0;
  151.     tmp_vec->gdb_line_lines=(struct g_line *)xmalloc(MAX_LINES_PER_VECTOR*sizeof(struct g_line));
  152.     tmp_vec->gdb_line_next_vector=f->gdb_line_file_vectors;
  153.     f->gdb_line_file_vectors=tmp_vec;
  154.     return tmp_vec;
  155. }
  156.  
  157. /* All done.  Time to write the stuff out.  This should be fun. */
  158. void
  159. gdb_lines_emit()
  160. {
  161.     struct g_line_file *f;
  162.     struct g_line_vector *v,*old_v,*v_tmp;
  163.     int    *tmp_table;
  164.     int    max_table_size;            /* m */
  165.     int    current_table_size;        /* s */
  166.     int    *current_table_pointer;        /* tp */
  167.     struct g_line *current_line_pointer;    /* lp */
  168.     unsigned long    table_offset_in_file;
  169.     int    n;
  170.     int    previous_line_number;
  171.     long int current_gdb_segment_pos;
  172.     unsigned int number_of_things_in_table;
  173.  
  174.     for(f=first_file;f;f=f->gdb_line_file_next_file) {
  175.         if(!f->gdb_line_table_offset) {
  176.             as_warn("No .gdblinetab given for file %d.  Ignoring .gdbline(s) for it.");
  177.             continue;
  178.         }
  179.  
  180.         /* Reverse the linked list of vectors.  Since we built it
  181.            last entry first, this puts the first entry at the start
  182.            of the list.  Thus we can manage to put out low line #s
  183.            at the start of the table. . .*/
  184.         v_tmp=0;
  185.         old_v=0;
  186.         for(v=f->gdb_line_file_vectors;v;v=v_tmp) {
  187.             v_tmp=v->gdb_line_next_vector;
  188.             v->gdb_line_next_vector=old_v;
  189.             old_v=v;
  190.         }
  191.         f->gdb_line_file_vectors=old_v;
  192.  
  193.         /* Start putting stuff at the beginning of the table */
  194.         current_gdb_segment_pos=f->gdb_line_table_offset+sizeof(long int);
  195.         previous_line_number = -2;
  196.         number_of_things_in_table = 0;
  197.  
  198.         /* For every vector in the table: */
  199.         for(v=f->gdb_line_file_vectors;v;v=v->gdb_line_next_vector) {
  200.             current_line_pointer=v->gdb_line_lines;
  201.  
  202.             /* For every element of every vector */
  203.             for(n=v->gdb_line_number_of_lines;n;n--) {
  204.  
  205.                 if(current_line_pointer->gdb_line_line_number != previous_line_number + 1) {
  206.                     /* Write out the line number */
  207.                     gdb_alter(current_gdb_segment_pos, -(current_line_pointer->gdb_line_line_number));
  208.                     current_gdb_segment_pos+=sizeof(long int);
  209.                     number_of_things_in_table++;
  210.                 }
  211.                 previous_line_number = current_line_pointer->gdb_line_line_number;
  212.  
  213.                 /* And write out the address */
  214.                 gdb_alter(current_gdb_segment_pos,current_line_pointer->gdb_line_frag->fr_address+current_line_pointer->gdb_line_offset);
  215.                 current_gdb_segment_pos+=sizeof(long int);
  216.                 number_of_things_in_table++;
  217.  
  218.                 current_line_pointer++;
  219.             }
  220.         }
  221.         gdb_alter(f->gdb_line_table_offset,number_of_things_in_table);
  222.     }
  223. }
  224.